﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using WebAPITest.Models;
using WebAPITest.Models.Database;
using WebAPITest.Service;

namespace WebAPITest.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class RedisController : ControllerBase
    {
        //Data Source=119.29.63.234;Initial Catalog=WebEnterpriseII;User ID=stu;Password=123456
        //包源 名称：nuget.org 源：https://api.nuget.org/v3/index.json
        private readonly IDatabase _redis;
        
        public RedisController(Models.RedisHelper client)
        {
            //创建Redis连接对象
            _redis = client.GetDatabase();
        }
        private readonly WebEnterpriseIIContext _db;
        //注入Redis服务
        private readonly IRedisService _redisService;
        public RedisController (IRedisService redisService)
        {
            _redisService = redisService;
        }

        [HttpGet]
        public void SetRedisCache()
        {
            _redis.StringSet("RedisCache", "666");
        }

        [HttpGet]
        public void RedisString()
        {
            var str = "广东工程职业技术学院";
            //写入String的值
            _redis.StringSet("StringCache", str);

            //获取String缓存的值
            var value = _redis.StringGet("StringCache");

            //追加字符
            _redis.StringAppend("StringCache", "666");

            //写入数据 5小时5分钟5秒 后过期
            _redis.StringSet("StringCache1", 1, new TimeSpan(5, 5, 5));

            //key为StringCache1的值自增1
            _redis.StringIncrement("StringCache1");

            //key为StringCache1的值增加10
            _redis.StringIncrement("StringCache1", 10);

            //key为StringCache1的值自减1
            _redis.StringDecrement("StringCache1");

            //key为StringCache1的值减少5
            _redis.StringDecrement("StringCache1", 5);
        }


        [HttpGet]
        public void RedisString2()
        {
            //添加key为goodName,value为"华为手机"的string类型数据
            var str = "华为手机";
            _redis.StringSet("goodName", str);
            //获取key为goodName的数据
            _redis.StringGet("goodName");
            //把key为goodName的数据，value设置为"小米手机"，并且设置过期时间为20秒
            _redis.StringSet("goodName", "小米手机", new TimeSpan(0, 0, 20));
            //在key为goodName的值后面添加字符串"666"
            _redis.StringAppend("goodName", "666");

        }

        [HttpGet]
        public void RedisHash()
        {
            //把以上json数据使用hash的数据格式添加redis数据库中，key为"liubeiinfo"
            var hashkey = "liuinfo";
            var hashEntrys = new HashEntry[]
            {
                new HashEntry("name","张开"),
                new HashEntry("class","软件技术"),
                new HashEntry("school","广工"),
                new HashEntry("age","18"),
                new HashEntry("num","2645464567"),
            };
            _redis.HashSet(hashkey,hashEntrys);
            //获取显示上述hash数据所有属性
            _redis.HashGetAll(hashkey);
            //修改学号num的值为"1406200230"
            _redis.HashSet("hashkey", "num", "16546516");
            //查询修改后学号的值
            _redis.HashGet("hashky", "num");
        }
        [HttpGet]
        public void RedisList()
        {
            //数据列表使用list数据格式以上述指定顺序添加到redis数据库中,key为"userList"
            var listkey = "userList";
            var listValue = new RedisValue[]
            {
                "刘备","关羽","张飞","赵云","马超","张开","曹操"
            };
            _redis.ListLeftPush(listkey, listValue);
            //查看目前列表数据并核对顺序
            _redis.ListRange(listkey, 0, -1);
            //赵云和马超中间加入"黄盖"
            _redis.ListInsertAfter(listkey,"赵云","黄盖");
            _redis.ListRange(listkey, 0, -1);
        }
        [HttpGet]
        public void RedisSet()
        {
            var setkey = "followList_liu";
            var setkey2 = "followList_zhang";
            var setValue = new RedisValue[]
            {
                1561,163515,1564,1345,54654,45466
            };
            _redis.SetAdd(setkey, setValue);
            var setValue2 = new RedisValue[]
            {
                12651,1561,1564,1345,4561
            };
            _redis.SetAdd(setkey2, setValue2);
            //使用set类型数据命令获取刘备同学和张飞同学共同关注的人
            var setValue3 = _redis.SetCombine(SetOperation.Intersect, setkey, setkey2);
        }
        [HttpGet]
        public void RedisZset()
        {
            var Zsetkey = "scorelist";
            var Value = new[]
            {
                new SortedSetEntry("张三",30),
                new SortedSetEntry("李四",50),
                new SortedSetEntry("刘备",68),
                new SortedSetEntry("马超",70),
                new SortedSetEntry("张开",80),

            };
            _redis.SortedSetAdd(Zsetkey, Value);
            //查询分数高的排名为第2 - 5名成绩的同学名单
            var Value1 = _redis.SortedSetRangeByRank(Zsetkey, 1, 4);
            var value2 = _redis.SortedSetRangeByScore(Zsetkey, 60, 100);
        }
        [HttpGet]
        public void SerializeJSON()
        {
            //查询商品
            var good = _db.Goods.FirstOrDefault(x => x.Id == 10);
            //转化为jsonStr字符串
            var jsonStr = JsonConvert.SerializeObject(good);
            //json字符串保存到redis
            _redis.StringSet("goodinfo", jsonStr);
            //从redis取出json字符串
            var redisStr = _redis.StringGet("goodinfo");
            //转化为对象
            var jsonObj = JsonConvert.DeserializeObject<Good>(redisStr);
        }
        //[HttpGet]
        //public List<Good> GetGoodsList()
        //{
        //    //获取redis的缓存 看有无数据
        //    var cache = _redis.StringGet("GoodCache");
        //    if (cache.HasValue)
        //    {
        //        //转化为对象  反序列化
        //        var jsonObj = JsonConvert.DeserializeObject<List<Good>>(cache);
        //        return jsonObj;
        //    }
        //    else
        //    {
        //        var goods = _db.Goods.ToList();
        //        //转化为json字符串 序列化
        //        var jsonStr = JsonConverter.SerializeObject(goods);
        //        //设置字符串缓存
        //        _redis.StringGet("GoodCache", jsonStr, new TimeSpan(0, 30, 0));
        //        return goods;
        //    }

        //}
        [HttpGet]
        /// <summary>
        /// 获取商品详情 使用List
        /// </summary>
        /// <param name="goodId"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize] //授权
        public Good GetGoodInfo1(int goodId)
        {
            //商品详情
            var good = _db.Goods.FirstOrDefault(x => x.Id == goodId);

            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;

            //使用redis取代本地缓存
            ////之前缓存下来的浏览记录  每个用户浏览记录都是单独的 每个用户都有自己的key  UserViews28\UserViews20
            //var key = $"UserViews{userId}";

            ////在用户浏览商品的时候 添加商品浏览记录 商品
            ////新数据在左边还是右边
            ////最近浏览的商品
            ////新 旧

            //var jsonStr = JsonConvert.SerializeObject(good);//序列化
            //_redis.ListLeftPush(key, jsonStr);// 1 1 1
            //使用服务
            _redisService.AddGoodViews(Convert.ToInt32(userId), good);

            return good;
        }
        /// <summary>
        /// 获取商品详情 使用ZSet 分数 
        /// </summary>
        /// <param name="goodId"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize] //授权
        public Good GetGoodInfo2(int goodId)
        {
            //商品详情
            var good = _db.Goods.FirstOrDefault(x => x.Id == goodId);

            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;

            //使用redis取代本地缓存
            ////之前缓存下来的浏览记录  每个用户浏览记录都是单独的 每个用户都有自己的key  UserViews28\UserViews20
            var key = $"UserViews{userId}";

            //记录商品浏览时间 把分数和时间关联
            //在用户浏览商品的时候 添加商品浏览记录 商品 
            //新数据在左边还是右边
            //最近浏览的商品
            //新 旧

            //浏览商品时间的时间戳 1970年1月1日 0时0分0秒(北京时间要加8个小时) 到现在的时间 就是时间戳
            var score = (DateTime.Now - new DateTime(1970, 1, 1, 8, 0, 0)).TotalSeconds;

            var jsonStr = JsonConvert.SerializeObject(good);//序列化
            _redis.SortedSetAdd(key, jsonStr, score);// 1 1 1

            //以浏览时间为分数的 商品数据 
            //1、获取到最新的浏览商品记录
            //2、获取到商品浏览时间

            //数据类型的使用实战技巧

            return good;
        }



        [HttpGet]
        [Authorize] //授权
        //添加购物车
        public string AddCar(int goodId)
        {
            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //每个用户的key
            var key = "car_"+userId;
            //添加一个购物车商品
            _redis.HashIncrement(key, goodId);

            return "添加成功";
        }

        [HttpGet]
        [Authorize] //授权
        //减少购物车
        public string DiffCar(int goodId)
        {
            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //每个用户的key
            var key = "car_" + userId;
            //添加一个购物车商品
            var count= _redis.HashIncrement(key, goodId);
            //减少之后如果是0 就删掉
            if (count == 0)
            {
                _redis.HashDelete(key, goodId);
            }
            return "减少成功";
        }
        [HttpGet]
        [Authorize] //授权
        //删除购物车
        public string DeleteCar(int goodId)
        {
            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //每个用户的key
            var key = "car_" + userId;
            _redis.HashDelete(key, goodId);
            return "删除成功";
        }

        [HttpGet]
        [Authorize] //授权
        //查询购物车商品
        public List<GetCarModel> GetCar()
        {
            //使用本地缓存保存登录用户浏览商品记录(多个商品)
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //每个用户的key
            var key = "car_" + userId;
            //查询hash所有数据
            var data = _redis.HashGetAll(key);
            var list=new List<GetCarModel>();
            //循环遍历hash所有数据 添加到模型
            foreach(var item in data)
            {
                //通过商品Id查询详细信息
                var good = _db.Goods.FirstOrDefault(x => x.Id == (int)item.Name);
                if (good != null)
                {
                    list.Add(new GetCarModel()
                    {
                        goodId = (int)item.Name,
                        Count = (int)item.Value,
                        Name = good.Name,
                        Price = good.Price,
                        Cover = good.Cover
                    });
                }
            }
            return list;
        }



        [HttpGet]
      
        //给搜索词添加搜索次数
        public string AddKeyWord(string keyword)
        {
            var key = "hotkey";
            //添加分数 添加次数
            _redis.SortedSetIncrement(key, keyword, 1);
            return "添加成功";

        }

        //查询前10名热搜结果及搜索次数
        [HttpGet]
        public List<GetKeyWordModel> GetKeyWord()
        {
            var key = "hotkey";
            //添加分数 添加次数
            var data = _redis.SortedSetRangeByRankWithScores(key, 0, 9, Order.Descending);
            var list = new List<GetKeyWordModel>();
            foreach (var item in data)
            {
                list.Add(new GetKeyWordModel()
                {
                    Keyword = item.Element,
                    Count = item.Score
                });
            }
            return list;
        }


        //关注用户和取消关注用户
        [HttpGet]
        [Authorize]
        public string FollowUser(int followUserId)
        {
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "follow_" + userId;
            _redis.SetAdd(key, followUserId);
            return "关注成功";
        }
        [HttpGet]
        [Authorize]
        public string UnFollowUser(int followUserId)
        {
            var userId = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            var key = "follow_" + userId;
            _redis.SetRemove(key, followUserId);
            return "取消关注成功";
        }
        //查看某个用户关注的人
        [HttpGet]
        public List<int> GetFollowUserList(int userId)
        {
            var key = "follow_" + userId;
            var data = _redis.SetMembers(key);
            return data.Select(x => (int)x).ToList();
        }
        //获取两个用户同时关注的人
        //查看某个用户关注的人
        [HttpGet]
        public List<int> GetFollowUserListIntersect(int userId1, int userId2)
        {
            var key = "follow_";
            //求交集
            var data = _redis.SetCombine(SetOperation.Intersect, key + userId1, key + userId2);
            return data.Select(x => (int)x).ToList();
        }
        //获取两个用户关注的用户总和
        [HttpGet]
        public List<int> GetFollowUserListUnion(int userId1, int userId2)
        {
            var key = "follow_";
            //求并集
            var data = _redis.SetCombine(SetOperation.Union, key + userId1, key + userId2);
            return data.Select(x => (int)x).ToList();
        }
        //当A进入B页面,求可能认识的人：这里指的是关注B中的用户 扣去 里面也关注A的用户，就是A可能认识的人。
        [HttpGet]
        public List<int> GetFollowUserListDifference(int userId1, int userId2)
        {
            var key = "follow_";
            //求差集
            var data = _redis.SetCombine(SetOperation.Difference, key + userId1, key + userId2);
            return data.Select(x => (int)x).ToList();
        }
    }




}
